package com.ruoyi.basic.service.impl;

import java.text.SimpleDateFormat;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.api.system.domain.SysDept;
import com.ruoyi.api.system.domain.SysUser;
import com.ruoyi.api.system.mapper.SysDeptMapper;
import com.ruoyi.api.system.mapper.SysUserMapper;
import com.ruoyi.api.system.utils.CacheUtils;
import com.ruoyi.api.system.utils.ShiroUtils;
import com.ruoyi.basic.constant.BasicConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.ZtreeString;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.mapper.SysUserRoleMapper;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.basic.mapper.BasicUserMapper;
import com.ruoyi.basic.domain.BasicUser;
import com.ruoyi.basic.service.IBasicUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 用户基本信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2021-08-19
 */
@Service
public class BasicUserServiceImpl extends ServiceImpl<BasicUserMapper, BasicUser> implements IBasicUserService
{

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    /**
     * 查询用户基本信息
     * 
     * @param id 用户基本信息主键
     * @return 用户基本信息
     */
    @Override
    public BasicUser selectBasicUserById(Long id)
    {
        return baseMapper.selectBasicUserById(id);
    }

    /**
     * 查询用户基本信息
     *
     * @param idCard 用户基本信息主键
     * @return 用户基本信息
     */
    @Override
    public BasicUser selectBasicUserByIdCard(String idCard)
    {
        return baseMapper.selectBasicUserByIdCard(idCard);
    }

    /**
     * 查询用户基本信息列表
     * 
     * @param basicUser 用户基本信息
     * @return 用户基本信息
     */
    @Override
    public List<BasicUser> selectBasicUserList(BasicUser basicUser)
    {
        return baseMapper.selectBasicUserList(basicUser);
    }

    /**
     * 新增用户基本信息
     * 
     * @param basicUser 用户基本信息
     * @return 结果
     */
    @Override
    public int insertBasicUser(BasicUser basicUser)
    {
        basicUser.setCreateTime(DateUtils.getNowDate());
        baseMapper.insert(basicUser);
        List<SysDept> deptList = deptMapper.selectDeptList(new SysDept());
        List<ZtreeString> ztrees = initZtree(deptList);
        CacheUtils.put("ztrees", ztrees);
        return 1;
    }

    /**
     * 修改用户基本信息
     * 
     * @param basicUser 用户基本信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int updateBasicUser(BasicUser basicUser)
    {
        SysUser sysUser = userMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getLoginName, basicUser.getIdCard()).last("limit 1"));
        if(StringUtils.isNotNull(sysUser)){
            if(!sysUser.getDeptId().equals(basicUser.getDeptId())){
                sysUser.setDeptId(basicUser.getDeptId());
                userMapper.updateById(sysUser);
            }
        }
        basicUser.setUpdateTime(DateUtils.getNowDate());
        baseMapper.updateById(basicUser);
        List<SysDept> deptList = deptMapper.selectDeptList(new SysDept());
        List<ZtreeString> ztrees = initZtree(deptList);
        CacheUtils.put("ztrees", ztrees);
        return 1;
    }

    /**
     * 批量删除用户基本信息
     * 
     * @param ids 需要删除的用户基本信息主键
     * @return 结果
     */
    @Override
    public int deleteBasicUserByIds(String ids)
    {
        return baseMapper.deleteBatchIds(Arrays.asList(Convert.toLongArray(ids)));
    }

    /**
     * 删除用户基本信息信息
     * 
     * @param id 用户基本信息主键
     * @return 结果
     */
    @Override
    public int deleteBasicUserById(Long id)
    {
        return baseMapper.deleteById(id);
    }

    /**
     * 导入用户数据
     *
     * @param userList 用户数据列表
     * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
     * @param operName 操作用户
     * @return 结果
     */
    @Override
    public String importUser(List<BasicUser> userList, Boolean isUpdateSupport, String operName)
    {
        if (StringUtils.isNull(userList) || userList.size() == 0)
        {
            throw new ServiceException("导入用户数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        int row = 2;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (BasicUser user : userList)
        {
            try
            {
                if(StringUtils.isEmpty(user.getDeptName())){
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、第" + row + "行，部门信息不存在");
                    continue;
                }
                //获取用户部门信息
                SysDept dept = deptMapper.selectOne(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDeptName, user.getDeptName()));
                if(StringUtils.isNotNull(dept)) {
                    user.setDeptId(dept.getDeptId());
                }else{
                    dept = new SysDept();
                    dept.setDeptName(user.getDeptName());
                    dept.setParentId(100L);
                    String deptId = Integer.toString(deptMapper.insert(dept));
                    user.setDeptId(Long.parseLong(deptId));
                }
                if(StringUtils.isEmpty(user.getUserNo())){
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、第" + row + "行，工号信息不存在");
                    continue;
                }
                BasicUser info = baseMapper.selectOne(new LambdaQueryWrapper<BasicUser>()
                        .eq(BasicUser::getIdCard, user.getIdCard()).last("limit 1"));
                if (StringUtils.isNull(info))
                {
                    user.setCreateBy(operName);
                    this.insertBasicUser(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、姓名 " + user.getName() + " 导入成功");
                }
                else if (isUpdateSupport)
                {
                    user.setId(info.getId());
                    user.setUpdateBy(operName);
                    this.updateBasicUser(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、姓名 " + user.getName() + " 更新成功");
                }
                else
                {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、姓名 " + user.getName() + " 已存在");
                }
            }
            catch (Exception e)
            {
                failureNum++;
                String msg = "<br/>" + failureNum + "、姓名 " + user.getName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }finally {
                row++;
            }
        }
        if (failureNum > 0)
        {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        }
        else
        {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    /**
     * 更新岗位工资
     *
     * @param userList 用户数据列表
     * @param operName 操作用户
     * @return 结果
     */
    @Override
    public String importUserDate(List<BasicUser> userList, String operName)
    {
        if (StringUtils.isNull(userList) || userList.size() == 0)
        {
            throw new ServiceException("导入数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        int row = 2;
        String REGEX_LOCALE_ENGLISH = "^[a-zA-Z]{3}\\s[a-zA-Z]{3}\\s\\d{2}\\s\\d{2}:\\d{2}:\\d{2}\\s[A-Z]{3}\\s\\d{4}$";
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (BasicUser user : userList)
        {
            try
            {
                if(StringUtils.isEmpty(user.getIdCard())){
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、第" + row + "行，人员身份证号信息不存在");
                    continue;
                }
                BasicUser info = baseMapper.selectOne(new LambdaQueryWrapper<BasicUser>()
                        .eq(BasicUser::getIdCard, user.getIdCard()).last("limit 1"));
                if (StringUtils.isNotNull(info))
                {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);

                    // 出生日期
                    if(user.getBirthday().matches(REGEX_LOCALE_ENGLISH)) {
                        Date birthday = dateFormat.parse(user.getBirthday());
                        user.setBirthday(DateUtils.parseDateToStr("yyyy-MM-dd", birthday));
                    }

                    // 组织时间
                    if(user.getPoliticalTime().matches(REGEX_LOCALE_ENGLISH)) {
                        Date politicalTime = dateFormat.parse(user.getPoliticalTime());
                        user.setPoliticalTime(DateUtils.parseDateToStr("yyyy-MM-dd", politicalTime));
                    }

                    // 入院时间
                    if(user.getHospitalTime().matches(REGEX_LOCALE_ENGLISH)) {
                        Date hospitalTime = dateFormat.parse(user.getHospitalTime());
                        user.setHospitalTime(DateUtils.parseDateToStr("yyyy-MM-dd", hospitalTime));
                    }

                    // 离院时间
                    if(user.getLeaveTime().matches(REGEX_LOCALE_ENGLISH)) {
                        Date leaveTime = dateFormat.parse(user.getLeaveTime());
                        user.setLeaveTime(DateUtils.parseDateToStr("yyyy-MM-dd", leaveTime));
                    }

                    user.setUpdateBy(operName);
                    user.setUpdateTime(DateUtils.getNowDate());
                    baseMapper.updateById(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、第" + row + "行，用户 " + user.getName() + " 更新成功");
                }
                else
                {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、第" + row + "行，用户 " + user.getName() + " 不存在");
                }
            }
            catch (Exception e)
            {
                failureNum++;
                String msg = "<br/>" + failureNum + "、姓名 " + user.getName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
            finally {
                row++;
            }
        }
        if (failureNum > 0)
        {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        }
        else
        {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    /**
     * 校验工号是否唯一
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public String checkUserNoUnique(BasicUser user){
        Long id = StringUtils.isNull(user.getId()) ? -1L : user.getId();
        BasicUser info = baseMapper.selectOne(new LambdaQueryWrapper<BasicUser>().eq(BasicUser::getUserNo, user.getUserNo()));
        if (StringUtils.isNotNull(info) && info.getId().longValue() != id.longValue())
        {
            return BasicConstants.USER_NO_NOT_UNIQUE;
        }
        return BasicConstants.USER_NO_UNIQUE;
    }

    /**
     * 校验身份证号是否唯一
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public String checkIdCardUnique(BasicUser user){
        Long id = StringUtils.isNull(user.getId()) ? -1L : user.getId();
        BasicUser info = baseMapper.selectOne(new LambdaQueryWrapper<BasicUser>().eq(BasicUser::getIdCard, user.getIdCard()));
        if (StringUtils.isNotNull(info) && info.getId().longValue() != id.longValue())
        {
            return BasicConstants.ID_CARD_NOT_UNIQUE;
        }
        return BasicConstants.ID_CARD_UNIQUE;
    }

    /**
     * 用户同步
     *
     * @param userIds 需要同步的用户id
     * @return 结果
     */
    @Override
    public String syncUser(String userIds){
        int successNum = 0;
        StringBuilder successMsg = new StringBuilder();
        for (Long userId : Convert.toLongArray(userIds)) {
            BasicUser basicUser = baseMapper.selectBasicUserById(userId);
            if(StringUtils.isNotEmpty(basicUser.getIdCard())){
                SysUser sysUser = userMapper.selectUserByLoginName(basicUser.getIdCard());
                if(StringUtils.isNotNull(sysUser)){
                    sysUser.setSex(basicUser.getSex());
                    sysUser.setDeptId(basicUser.getDeptId());
                    sysUser.setUserName(basicUser.getName());
                    sysUser.setUpdateTime(DateUtils.getNowDate());
                    userMapper.updateById(sysUser);
                }else{
                    sysUser = new SysUser();
                    sysUser.setLoginName(basicUser.getIdCard());
                    sysUser.setUserName(basicUser.getName());
                    sysUser.setSex(basicUser.getSex());
                    sysUser.setDeptId(basicUser.getDeptId());
                    String salt = ShiroUtils.randomSalt();
                    sysUser.setSalt(salt);
                    sysUser.setPassword(new Md5Hash(basicUser.getIdCard() + "123456" + salt).toHex());
                    sysUser.setCreateTime(DateUtils.getNowDate());
                    userMapper.insert(sysUser);

                    SysUserRole sysUserRole = new SysUserRole();
                    sysUserRole.setUserId(sysUser.getUserId());
                    sysUserRole.setRoleId(2L);
                    userRoleMapper.insert(sysUserRole);
                }
                successNum++;
                successMsg.append("<br/>" + successNum + "、员工 " + basicUser.getName() + " 同步成功");
            }
        }
        return successMsg.toString();
    }

    /**
     * 查询部门管理树
     *
     * @return 所有部门信息
     */
    @Override
    public List<ZtreeString> selectUserTree(SysDept dept)
    {
        List<SysDept> deptList = deptMapper.selectDeptList(dept);
        Object object = CacheUtils.get("ztrees");
        List<ZtreeString> ztrees = null;
        if(StringUtils.isNotNull(object)){
            ztrees = (List<ZtreeString>) object;
        } else {
            ztrees = initZtree(deptList);
            CacheUtils.put("ztrees", ztrees);
        }
        return ztrees;
    }

    /**
     * 对象转部门树
     *
     * @param deptList 部门列表
     * @return 树结构列表
     */
    public List<ZtreeString> initZtree(List<SysDept> deptList)
    {
        List<ZtreeString> ztrees = new ArrayList<ZtreeString>();
        for (SysDept dept : deptList)
        {
            if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()))
            {
                ZtreeString ztree = new ZtreeString();
                ztree.setId("d_" + dept.getDeptId());
                ztree.setpId("d_" + dept.getParentId());
                ztree.setName(dept.getDeptName());
                ztree.setTitle(dept.getDeptName());
                ztree.setType("dept");
                ztrees.add(ztree);

                List<BasicUser> userList = baseMapper.selectList(new LambdaQueryWrapper<BasicUser>()
                        .eq(BasicUser::getDeptId, dept.getDeptId()).in(BasicUser::getUserType, Convert.toStrArray("00,01,6")));
                if(StringUtils.isNotEmpty(userList)){
                    this.initZtree(ztrees, userList);
                }
            }
        }
        return ztrees;
    }

    /**
     * 对象转部门树
     *
     * @return 树结构列表
     */
    public List<ZtreeString> initZtree(List<ZtreeString> ztrees, List<BasicUser> userList)
    {
        for (BasicUser user : userList)
        {
            ZtreeString ztree = new ZtreeString();
            ztree.setId("u_" + user.getId());
            ztree.setpId("d_" + user.getDeptId());
            ztree.setName(user.getName() + "(" + user.getUserNo() + ")");
            ztree.setTitle(user.getName() + "(" + user.getUserNo() + ")");
            ztree.setType("user");
            ztrees.add(ztree);
        }
        return ztrees;
    }
}
